﻿using System;
using System.Collections.Generic;
using System.Linq;
using Fee.Stores;
using Fee.VendorMatchers;
using Identity;
using Ornament.ImportHelper;
using Text.Helper;

namespace Fee.IO.Importers
{
    public class VendorMatcherImporter<T> : BaseImporter<T> where T : FeeDbContext
    {
        private const int YEAR_POSITION = 0;
        private const int DISTRICT_POS = 1;
        private const int CONSTRUCTION_POS = 2;
        private const int STATION_POS = 3;
        private const int VENDOR_POS = 4;
        private const int CONTRACT_POS = 5;
        private readonly IVendorMatcherStore<T> _matcherStore;

        public VendorMatcherImporter(T context, IVendorMatcherStore<T> matcherStore) : base(context, true)
        {
            _matcherStore = matcherStore;
        }

        protected override bool ConverTo(IList<string> rowStringInfo, out ImportResultItem item)
        {
            item = new ImportResultItem();
            //  年份 区域  建设类型 站点类型    单位 类型


            //年份
            var error = !int.TryParse(rowStringInfo[YEAR_POSITION], out var year);
            if (error)
                item.AddError(YEAR_POSITION, "年份格式不正确");

            var isVip = false;
            District district = null;
            //区域
            var districtName = rowStringInfo[DISTRICT_POS];
            if (districtName == "重客")
            {
                isVip = true;
            }
            else
            {
                district = Context.Districts.FirstOrDefault(f => f.Name == districtName);
                if (district == null) item.AddError(1, "区域不存在");
            }


            //建设类型
            var constructionTypes = GetConstructionTypes(rowStringInfo, item);
            //站点类型
            var stationTypes = GetStationTypes(rowStringInfo, item);

            //合约类型
            var contractTypes = GetContractTypes(rowStringInfo, item);
            //当合约类型 带有施工的时候，stationTypes 绝对不能为空
            if (contractTypes.Any(f => f == ContractType.Construction) && !stationTypes.Any())
                item.AddError(STATION_POS, "当为施工的时候，站点类型不能为\"无\"");

            //单位执行项目
            var vendorName = rowStringInfo[VENDOR_POS];
            var vendor = Context.Vendors.FirstOrDefault(f => f.Name == vendorName);
            if (vendor == null) item.AddError(VENDOR_POS, "供应商'" + vendorName + "'不存在");

            if (!item.HasError)
                foreach (var contractType in contractTypes)
                foreach (var constructionType in constructionTypes)
                {
                 
                    if (contractType == ContractType.Construction)

                    {
                        foreach (var baseStationType in stationTypes)
                        {
                            var matcher = GetOrCreate(contractType, baseStationType, district, year,
                                constructionType, isVip,
                                vendor);
                            item.Data.Add(matcher);
                        }
                    }
                    else
                    {
                       var matcher = GetOrCreate(contractType, null, district, year,
                            constructionType, isVip,
                            vendor);
                        item.Data.Add(matcher);
                    }
                }


            return item.CellErrors.Count == 0;
        }


        private VendorMatcher GetOrCreate(ContractType contractType, StationType? stationType, District district,
            int year, ConstructionType constructionType, bool isVip, Vendor vendor)
        {
            VendorMatcher matcher;
            switch (contractType)
            {
                case ContractType.Design:

                    var designVendorMatcher = _matcherStore.GetDesign(district, year, constructionType);

                    matcher = designVendorMatcher ?? new DesignVendorMatcher()
                        ;
                    break;
                case ContractType.Construction:
                    if (stationType == null)
                        throw new Exception("当类型为施工的时候，基站类型不能为空");
                    var impleVendorMatcher = _matcherStore.GetImple(district, stationType,
                        year, constructionType);
                    matcher = impleVendorMatcher ?? new ConstructionVendorMatcher
                    {
                        StationType = stationType.Value,
                        IsVip = isVip
                    };

                    break
                        ;
                case ContractType.Supervisor:

                    var supervisorVendorMatcher = _matcherStore.GetSupervisor(district, year, constructionType);
                    matcher = supervisorVendorMatcher ?? new SupervisorVendorMatcher()
                        ;
                    break;
                default:
                    throw new Exception();
            }

            matcher.Vendor = vendor;
            matcher.District = district;
            matcher.ConstructionType = constructionType;
            matcher.Year = year;
            return matcher;
        }

        private static List<ConstructionType> GetConstructionTypes(IList<string> rowStringInfo,
            ImportResultItem importImportResultItem)
        {
            var constructionTypeDesc = rowStringInfo[CONSTRUCTION_POS];
            var constructionTypes = new List<ConstructionType>();
            if (constructionTypeDesc == "所有")
            {
                foreach (ConstructionType constructionType in Enum.GetValues(typeof(ConstructionType)))
                    constructionTypes.Add(constructionType);
            }
            else
            {
                var error = !EnumHelper.TryFromDisplayName(constructionTypeDesc, out ConstructionType type);
                if (error)
                    importImportResultItem.AddError(CONSTRUCTION_POS, "建设类型不正确");
                else
                    constructionTypes.Add(type);
            }

            return constructionTypes;
        }


        private static List<StationType> GetStationTypes(IList<string> rowStringInfo,
            ImportResultItem importImportResultItem)
        {
            var stationTypeStr = rowStringInfo[STATION_POS];
            var stationTypes = new List<StationType>();
            switch (stationTypeStr)
            {
                case "无":
                    break;
                case "所有":
                    foreach (StationType value in Enum.GetValues(typeof(StationType))) stationTypes.Add(value);

                    break;
                default:
                    var error = !EnumHelper.TryFromDisplayName(stationTypeStr, out StationType stationType);
                    if (error)
                        importImportResultItem.AddError(STATION_POS, "如果为实施，站点类型类型必须填写");
                    else
                        stationTypes.Add(stationType);
                    break;
            }

            return stationTypes;
        }

        private static List<ContractType> GetContractTypes(IList<string> rowStringInfo,
            ImportResultItem importImportResultItem
        )
        {
            var result = new List<ContractType>();

            var contractTypeStr = rowStringInfo[CONTRACT_POS];
            switch (contractTypeStr)
            {
                case "无":
                    break;
                case "所有":
                    foreach (ContractType value in Enum.GetValues(typeof(ContractType))) result.Add(value);

                    break;
                default:
                    var error = !EnumHelper.TryFromDisplayName(contractTypeStr, out ContractType stationType);
                    if (error)
                        importImportResultItem.AddError(CONTRACT_POS, "合同类型无法识别：" + contractTypeStr);
                    else
                        result.Add(stationType);
                    break;
            }

            return result;
        }
    }
}